from gittle import Gittle
from gittle.auth import GittleAuth
from dulwich import client
import urlparse,Queue,threading,time,os,json



class FixGittle(Gittle):
	"""docstring for Git"""

	def get_client(self, origin_uri=None, **kwargs):
		origin_uri = origin_uri or self.origin_uri or InvalidRemoteUrl()
		client_kwargs = {}
		auth_kwargs = self.authenticator.kwargs()

 		client_kwargs.update(auth_kwargs)
		client_kwargs.update(kwargs)
		client_kwargs.update({
            'report_activity': self.report_activity
        })

		client, remote_path = self.get_transport_and_path(origin_uri, **client_kwargs)
		return client, remote_path
	    
	def get_transport_and_path_from_url(self,url, config=None, **kwargs):
	    parsed = urlparse.urlparse(url)
	    if parsed.scheme == 'git':
	        return (client.TCPGitClient(parsed.hostname, port=parsed.port, **kwargs),
	                parsed.path)
	    elif parsed.scheme == 'git+ssh':
	        path = parsed.path
	        if path.startswith('/'):
	            path = parsed.path[1:]
	        return client.SSHGitClient(parsed.hostname, port=parsed.port,
	                            username=parsed.username, **kwargs), path
	    elif parsed.scheme in ('http', 'https'):
	        return client.HttpGitClient(urlparse.urlunparse(parsed), config=config,
	                **kwargs), parsed.path
	    elif parsed.scheme == 'file':
	        return client.default_local_git_client_cls(**kwargs), parsed.path
	    raise ValueError("unknown scheme '%s'" % parsed.scheme)

	def get_transport_and_path(self,location, **kwargs):
	    try:
	        return self.get_transport_and_path_from_url(location, **kwargs)
	    except ValueError:
	        pass

	    if ':' in location and not '@' in location:
	        # SSH with no user@, zero or one leading slash.
	        (hostname, path) = location.split(':')
	        return client.SSHGitClient(hostname, **kwargs), path
	    elif '@' in location and ':' in location:
	        # SSH with user@host:foo.
	        user_host, path = location.split(':')
	        user, host = user_host.rsplit('@')
	        return client.SSHGitClient(host, username=user, **kwargs), path

	    # Otherwise, assume it's a local path.
	    return client.default_local_git_client_cls(**kwargs), location

class FairyGit(object):
	"""docstring for FairyGit"""

	def __init__(self, path,uri=None):
		self.git = None
		self.path = path
		self.uri = uri

	def auth(self, acc, pwd):
		self.auth = GittleAuth(username = acc, password = pwd)
		pass

	def synch(self,branch):
		try:
			self.pull()
		except:
			self.clone(branch)

	def pull(self):
		git = self.getGit()
		print git.pull()
		print git.commit_info()
		pass

	def clone(self,branch):
		try:
			git = FixGittle.clone(self.uri,self.path+"/.git", auth = self.auth,bare=True)
		except :
			pass
		git = self.getGit()
		git.switch_branch(branch)

	def getGit(self):
		if not self.git:
			self.git = FixGittle(self.path, self.uri, self.auth)
		return self.git


class Hooker:

	def __init__(self):
		self.queue = Queue.Queue()
		self.thread = None
		self.map = {}

	def getHookConfig(self,project,branch):
		configFile = "config/hook/"+project+".json"
		if(os.path.exists(configFile) == False):
			return None
		project = json.load(file(configFile))
		branch = project.get("branchs").get(branch)
		if branch == None:
			return
		project.update(branch)
		return project

	def runTask(self,project,branch):
		config = self.getHookConfig(project,branch)
		fairyGit = FairyGit(config['path'], config['url'])
		fairyGit.auth(config['acc'],config['pwd'])
		if config.get("before"):
			os.system(config.get("before").format(branch=branch))
		fairyGit.synch(branch)
		# fairyGit.git.commit_info()
		if config.get("after"):
			os.system(config.get("after").format(branch=branch))

	def worker(self):
		while not self.queue.empty():
			key = self.queue.get()
			del self.map[key]
			task = key.split(",")
			print key
			self.runTask(task[0],task[1])

	def addTask(self,project,branch):
		key = "%s,%s" % (project,branch)
		if self.getHookConfig(project,branch) == None or self.map.get(key) != None:
			return
		self.map[key] = 1
		self.queue.put(key)
		if(self.thread == None or (not self.thread.isAlive())):
			self.thread = threading.Thread(target=self.worker)
			self.thread.start()
